package com.bosssoft.client;

import com.bosssoft.exception.MyException;
import com.bosssoft.observer.ConcreteObserver;
import com.bosssoft.observer.Observer;
import com.bosssoft.observer.Subject;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

/**
 * BIO客户端类，实现了与服务端的基于生物识别技术（BIO）的通信。
 *
 * @author 戴圣燃
 * @Date  2024/5/26
 * @Description
 */
@Slf4j
public class Client {
    private static String id;
    private static Random random;
    static{
        try{
            random = SecureRandom.getInstanceStrong();
        }catch(NoSuchAlgorithmException e){
            log.info("Exception:{}",e.getMessage());
        }
    }
    /**
     * 程序入口，创建客户端并建立与服务端的连接，实现数据的发送和接收。
     *
     * @param args 命令行参数
     * @throws IOException 用于处理网络通信中的IO异常
     */
    public static void main(String[] args) throws IOException {
        // 初始化观察者模式，用于处理特定事件
        Subject subject = new Subject();
        Observer observer1 = new ConcreteObserver("Observer 1");
        subject.addObserver(observer1);
        subject.start();

        log.info("===========BIO客户端启动================");
        id = Client.setId(); // 生成并设置客户端ID
        log.info("本客户端id为" + id);

        /**
         * 连接服务端并持续通过用户指令进行数据的发送和接收。
         * 本段代码主要实现以下功能：
         * 1. 建立与服务端的TCP连接。
         * 2. 不断接收用户输入的指令，根据指令向服务端发送数据或者从服务端接收数据。
         * 3. 支持向所有客户端或指定客户端发送数据，并能从服务端接收数据。
         */
        Socket socket = new Socket("127.0.0.1", 8888); // 连接服务端
        while(true) {
            try  {
                // 循环接收用户输入的指令，直到接收到正确的指令
                log.info("请输入指令：");
                String mark = "error";
                while (mark.equals("error")) {
                    mark = Subject.scannerInstruct();
                }
                // 根据指令的不同类型，执行不同的数据发送和接收操作
                if (mark.substring(0, 9).equals("send @all")) {
                    // 向所有客户端发送数据，并接收服务端返回的数据
                    subject.sendDataToClient(socket, mark.substring(10, mark.length()), id, "all");
                    log.info("客户端开始接收中");
                    Subject.receiveDataFromServer(socket);
                    log.info("客户端接收完成");
                }
                else if (mark.substring(0, 6).equals("send @")) {
                    // 向指定客户端发送数据，并接收服务端返回的数据
                    subject.sendDataToClient(socket, mark.substring(13, mark.length()), id, mark.substring(6, 12));
                    log.info("客户端开始接收中");
                    Subject.receiveDataFromServer(socket);
                    log.info("客户端接收完成");
                }
                else if (mark.substring(0, 4).equals("send")) {
                    // 向服务端发送数据，并接收服务端返回的数据
                    Subject.sendDataToServer(socket, mark.substring(5, mark.length()), id);
                    log.info("服务端接收完成");
                    Subject.receiveDataFromServer(socket);
                }

            } catch (MyException e) {
                // 捕获并处理自定义异常
                log.info("Exception:{}",e.getMessage());
            }
        }

    }

    /**
     * 生成一个6位的随机数字ID。
     *
     * @return 生成的6位数字字符串ID
     */
    private static String setId() {
        StringBuilder sb = new StringBuilder(6);
        for (int i = 0; i < 6; i++) {
            int number = random.nextInt(10); // 生成0-9之间的随机数
            sb.append(number);
        }
        return sb.toString();
    }

}
